package com.philip;


import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgproc.cvtColor;
import static org.bytedeco.opencv.global.opencv_imgproc.rectangle;

import javax.swing.*;

import java.io.File;

import static org.bytedeco.opencv.global.opencv_imgproc.cvtColor;


/**
 * 调用本地摄像头窗口视频
 * 
 * @author eguid
 * @version 2016年6月13日
 * @see
 * @since javacv1.2
 */

public class FaceDetect {
  static {
    System.load("C:\\opencv\\opencv\\build\\java\\x64\\opencv_java412.dll");
  }
  public static void main(String[] args) throws Exception, InterruptedException {
    // 里面的整数值代表第N个摄像头，电脑内置默认为0，外置的从1开始
    OpenCVFrameConverter.ToMat converterToMat = new OpenCVFrameConverter.ToMat();
    OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
    grabber.start(); // 开始获取摄像头数据
    CanvasFrame canvas = new CanvasFrame("摄像头");// 新建一个窗口
    canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    canvas.setAlwaysOnTop(true);
    Frame videoFrame = null;
    Mat videoMat = null;
    while (true) {
      if (!canvas.isDisplayable()) {// 窗口是否关闭
        grabber.stop();// 停止抓取
        grabber.close();
        System.exit(2);// 退出
      }
      // 获取摄像头图像并放到窗口上显示， 这里的Frame是一帧视频图像
      videoFrame = grabber.grab();
      videoMat = converterToMat.convert(videoFrame);
      Mat videoMatGray = new Mat();
      // 图片灰度处理，更容易识别出人脸
      cvtColor(videoMat, videoMatGray, COLOR_BGRA2GRAY);
      Mat detectFace = detectFace(videoMat);
      videoFrame = converterToMat.convert(detectFace);
      canvas.showImage(videoFrame);// 显示带方框的人脸
      Thread.sleep(50);// 50毫秒刷新一次图像
    }
  }

  /**
   * 人脸检测
   * 
   * @param videoMat
   * @return
   * @throws Exception
   */
  public static Mat detectFace(Mat videoMat) throws Exception {

    System.out.println("Running DetectFace ... ");
    // 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器，该文件位于opencv安装目录中
    File file = Loader.cacheResource("haarcascade_frontalface_alt.xml");
    String classifierName = file.getAbsolutePath();

    CascadeClassifier faceDetector = new CascadeClassifier(classifierName);
    // 在图片中检测人脸
    RectVector faces = new RectVector();
    faceDetector.detectMultiScale(videoMat, faces);
    System.out.println(String.format("Detected %s faces", faces.size()));
    Rect[] rects = faces.get();
    if (rects != null && rects.length >= 1) {
      for (Rect rect : rects) {
        //  rectangle(videoMat, rect, Scalar.RED);
        cutoutFace(videoMat, rect);
        saveFace(videoMat, rect);
      }
    }
    faceDetector.close();
    return videoMat;
  }

  private static boolean compareSuccess (Mat videoMat) {
    boolean success = false;
    //轉化成原生的類型
    OpenCVFrameConverter.ToMat converter1 = new OpenCVFrameConverter.ToMat();
    OpenCVFrameConverter.ToOrgOpenCvCoreMat converter2 = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
    org.opencv.core.Mat mat = converter2.convert(converter1.convert(videoMat));
 //   org.opencv.core.Mat mat = new org.opencv.core.Mat(videoMat.address());
    File srcFile = new File("D:\\test\\capture\\1585131081026.jpg");
    double retVal = CompareFace.cmpPicByMat(srcFile.getAbsolutePath(),mat);
    System.out.println(retVal);
    if (retVal == 1) {
      success = true;
    }
    return success;
  }

  private static Mat cutoutFace(Mat originalImage, Rect rect){
    Mat sub = originalImage.rowRange(rect.y(), rect.y() + rect.height()).colRange(rect.x(), rect.x() + rect.width());
    Mat mat = new Mat();
    Size size = new Size(100, 100);
    resize(sub, mat, size);
    /*if (compareSuccess(mat)) {
      rectangle(originalImage, rect, Scalar.RED);
    }*/
    /*else {
      rectangle(originalImage, rect, Scalar.GREEN);
    }*/
    rectangle(originalImage, rect, Scalar.GREEN);
    return mat;
  }

  private static void saveFace(Mat originalImage, Rect rect){
    Mat cutoutFace=cutoutFace(originalImage,rect);
    boolean success= opencv_imgcodecs.imwrite("D:\\test\\capture\\" + System.currentTimeMillis() + ".jpg", cutoutFace);
    System.out.println("截取人脸成功： "+success);
  }

  /**
   * 抓取人脸保存为图片
   * 
   * @param image
   * @param rect
   */
//  private static void saveFace(Mat image, Rect rect) {
//    Mat sub = image.rowRange(rect.y(), rect.y() + rect.height()).colRange(rect.x(), rect.x() + rect.width());
//    Mat mat = new Mat();
//    Size size = new Size(100, 100);

//    resize(sub, mat, size);
//    boolean success= opencv_imgcodecs.imwrite("D:\\test\\capture\\" + System.currentTimeMillis() + ".jpg", mat);
//    System.out.println("截取人脸成功： "+success);
//  }
}